home *** CD-ROM | disk | FTP | other *** search
/ Aminet 21 / Aminet 21 (1997)(GTI - Schatztruhe)[!][Oct 1997].iso / Aminet / comm / bbs / cit_src_7H21.lha / floors.c < prev    next >
C/C++ Source or Header  |  1997-07-27  |  20KB  |  941 lines

  1. /*
  2. *       Floors.c
  3. *
  4. * Floor handling code for Citadel-86.
  5. */
  6. #include "ctdl.h"
  7. /*
  8. *       Contents
  9. */
  10. char SelDirs = FALSE,
  11. SelShared = FALSE,
  12. SelPriv = FALSE,
  13. SelRO = FALSE,
  14. SelNew = FALSE,
  15. SelAnon = FALSE;
  16. char ShowNew;
  17. char NotForgotten = TRUE;
  18. char JustChecking;
  19. char HasSkipped;
  20. static char maim;
  21. char FoundNew;
  22. static int  GlobalFloor;
  23. static int  MoveCount;
  24. extern struct floor  *FloorTab;
  25. extern rTable    *roomTab;
  26. extern CONFIG    cfg;
  27. extern aRoom     roomBuf;
  28. extern logBuffer logBuf;
  29. extern MessageBuffer   msgBuf;
  30. extern char      remoteSysop;
  31. extern int       thisRoom;
  32. extern char      loggedIn;       /* Are we logged in?            */
  33. extern int       TopFloor;
  34. extern char      *confirm;
  35. extern char      outFlag;
  36. extern char      onConsole;
  37. extern char      *baseRoom;
  38. static int FlagCheck(int i);
  39. int FindFloor(label name, char doPartial);
  40. /*
  41. * FloorRunner()
  42. *
  43. * This function runs through all the rooms on a floor, applying the given
  44. * function to all rooms on that floor.
  45. */
  46. int FloorRunner(int start, int (*func)(int r))
  47.   {
  48.   int rover, CurrentFloor;
  49.   if (start == ERROR) return ERROR;
  50.   CurrentFloor = roomTab[start].rtFlIndex;
  51.   if (!FloorTab[CurrentFloor].FlInuse)
  52.   CurrentFloor = 0;
  53.   /* start with current room, go through table */
  54.   for (rover = 0; rover < MAXROOMS; rover++)
  55.     {
  56.     /* deep breath ... should rewrite this, prime example of
  57.     programming via accretion. */
  58.     if (!FloorTab[roomTab[rover].rtFlIndex].FlInuse)
  59.     roomTab[rover].rtFlIndex = 0;
  60.     if ( roomTab[rover].rtFlIndex == CurrentFloor && (KnownRoom(rover) ||
  61.     (NotForgotten && roomTab[rover].rtflags.INUSE &&
  62.     (aide && (cfg.BoolFlags.aideSeeAll || onConsole) &&
  63.     (!roomTab[rover].rtflags.INVITE || SomeSysop())))))
  64.       {
  65.       if ((*func)(rover)) return rover;
  66.  
  67.       }
  68.  
  69.     }
  70.   return ERROR;
  71.  
  72.   }
  73. /*
  74. * NewRoom()
  75. *
  76. * This function gets next new room in system (like GotoRoom()) on the current
  77. * floor.
  78. */
  79. int NewRoom()
  80.   {
  81.   int CurrentFloor, OldFloor, roomNo;
  82.   OldFloor = thisFloor;
  83.   CurrentFloor = -1;
  84.   while (   (roomNo = FloorRunner(thisRoom, NSRoomHasNew)) == ERROR &&
  85.   CurrentFloor != TopFloor     )
  86.     {
  87.     thisRoom = FirstRoom(++CurrentFloor);
  88.  
  89.     }
  90.   if (CurrentFloor == TopFloor)
  91.   roomNo = 0;           /* no new-message rooms found */
  92.   getRoom(roomNo);
  93.   mPrintf("%s\n ", roomBuf.rbname);
  94.   /* really ugly kludge.  someday locate this gunk in gotoRoom() */
  95.   if (!KnownRoom(thisRoom))
  96.     {
  97.     SetKnown(0, MAXVISIT - 1, thisRoom, &logBuf);
  98.  
  99.     }
  100.   return !(OldFloor == roomTab[thisRoom].rtFlIndex);
  101.  
  102.   }
  103. /*
  104. * FirstRoom()
  105. *
  106. * This function gets the first room on the specified floor.
  107. */
  108. int FirstRoom(int FloorNo)
  109.   {
  110.   int rover;
  111.   for (rover = 0; rover < MAXROOMS; rover++)
  112.     {
  113.     if (     roomTab[rover].rtflags.INUSE &&
  114.     roomTab[rover].rtFlIndex == FloorNo    )
  115.     return rover;
  116.  
  117.     }
  118.   return ERROR;
  119.  
  120.   }
  121. /*
  122. * DoFloor()
  123. *
  124. * This function handles the fanout for floor commands.
  125. */
  126. int DoFloors()
  127.   {
  128.   int  toReturn;
  129.   char again, c[2];
  130.   char *FloorOpts[] =
  131.     {
  132.     TERM "Aide", TERM "Z\bForget", TERM "Skip",
  133.     TERM "Goto", TERM "Known Floors", TERM "C\b", ""
  134.  
  135.     };
  136.   SListBase  FSelects =
  137.     {
  138.     NULL, FindSelect, NULL, NoFree, NULL
  139.  
  140.     };
  141.   do
  142.     {
  143.     toReturn = GOOD_SELECT;
  144.     if (CmdMenuList(FloorOpts, &FSelects, "floor.mnu", c, TRUE, FALSE)
  145.     == BACKED_OUT) return GOOD_SELECT;
  146.     again = FALSE;
  147.     switch (c[0])
  148.       {
  149.       case 'A': toReturn = FAide();     break;
  150.       case 'Z': toReturn = FForget();     break;
  151.       case 'S':
  152.       case 'G': toReturn = FGotoSkip(c[0]);   break;
  153.       case 'K': toReturn = FKnown(ONLY_FLOORS);   break;
  154.       case 'C': toReturn = FConfigure();      break;
  155.       default:
  156.       ;
  157.  
  158.       }
  159.     if (toReturn == BACKED_OUT)
  160.       {
  161.       again = TRUE;
  162.       PushBack('\b');
  163.  
  164.       }
  165.  
  166.     }
  167.   while (again);
  168.   return toReturn;
  169.  
  170.   }
  171. /*
  172. * FInvite()
  173. *
  174. * This function is used to invite a user to all rooms on a floor.
  175. */
  176. void FInvite()
  177.   {
  178.   mPrintf("[%s]\n ", FloorTab[thisFloor].FlName);
  179.   getList(UserToFloor, "Invited users", NAMESIZE, FALSE);
  180.  
  181.   }
  182. static char YesInvite = TRUE;
  183. /*
  184. * FWithdraw()
  185. *
  186. * This function will withdraw invitations from a floor.
  187. */
  188. void FWithdraw()
  189.   {
  190.   mPrintf("[%s]\n ", FloorTab[thisFloor].FlName);
  191.   YesInvite = FALSE;
  192.   getList(UserToFloor, "Kicked out users", NAMESIZE, FALSE);
  193.   YesInvite = TRUE;
  194.  
  195.   }
  196. extern logBuffer logTmp;
  197. /*
  198. * UserToFloor()
  199. *
  200. * This function will invite the named user to current floor.  This function
  201. * is used in conjunction with getList().
  202. */
  203. int UserToFloor(char *name)
  204.   {
  205.   int logNo;
  206.   int InviteUserToFloor(int r);
  207.   logNo = findPerson(name, &logTmp);
  208.   if (logNo == ERROR)
  209.     Output_Citadel_Message("NODRFD", (long)name,NULL,NULL);
  210.   else
  211.     {
  212.     FloorRunner(thisRoom, InviteUserToFloor);
  213.     putLog(&logTmp, logNo);
  214.  
  215.     }
  216.   return TRUE;
  217.  
  218.   }
  219. /*
  220. * InviteUserToFloor()
  221. *
  222. * This function does the actual work of inviting a user.
  223. */
  224. int InviteUserToFloor(int r)
  225.   {
  226.   if (r != AIDEROOM)
  227.     {
  228.     if (YesInvite)
  229.     logTmp.lbgen[r] = (roomTab[r].rtgen << GENSHIFT) + MAXVISIT - 1;
  230.     else
  231.     logTmp.lbgen[r] = ((roomTab[r].rtgen + (MAXGEN-1)) % MAXGEN);
  232.  
  233.     }
  234.   return FALSE;
  235.  
  236.   }
  237. /*
  238. * FSkipped()
  239. *
  240. * This function will show skipped rooms and floors.
  241. */
  242. void FSkipped()
  243.   {
  244.   int rover, roomNo;
  245.   JustChecking = FALSE;
  246.   ShowNew = TRUE;
  247.   Output_Citadel_Message("SKPRMF",(long) FloorTab[thisFloor].FlName , NULL, NULL);
  248.   FloorRunner(thisRoom, SkippedNewRoom);
  249.   ShowNew = FALSE;
  250.   JustChecking = TRUE;
  251.   Output_Citadel_Message("SKPFLR", NULL, NULL, NULL);
  252.   for (rover = 1; rover < TopFloor; rover++)
  253.     {
  254.     roomNo = FirstRoom(rover);
  255.     if (FloorRunner(roomNo, SkippedNewRoom) != ERROR)
  256.       Output_Citadel_Message("FLRNNL",(long)FloorTab[rover].FlName , NULL, NULL);
  257.  
  258.     }
  259.   JustChecking = FALSE;
  260.   tableRunner(SkippedNewRoom, TRUE);
  261.  
  262.   }
  263. /*
  264. * FForget()
  265. *
  266. * This function will forget a floor.
  267. */
  268. char FForget()
  269.   {
  270.   Output_Citadel_Message("FLOORN",(long)FloorTab[roomTab[thisRoom].rtFlIndex].FlName, NULL, NULL);
  271.   if (!getYesNo("CONFRM")) return GOOD_SELECT;
  272.   FloorRunner(thisRoom, Zroom);
  273.   gotoRoom(baseRoom, 'S');
  274.   return GOOD_SELECT;
  275.  
  276.   }
  277. /*
  278. * FConfigure()
  279. *
  280. * This function will change floor configuration value.
  281. */
  282. char FConfigure()
  283.   {
  284.   FloorMode = !FloorMode;
  285.   mPrintf("%s mode\n ", (FloorMode) ? "FLOOR" : "Normal");
  286.   return GOOD_SELECT;
  287.  
  288.   }
  289. /*
  290. * FGotoSkip()
  291. *
  292. * This function will let us Skip an entire floor.
  293. */
  294. char FGotoSkip(int mode)
  295.   {
  296.   label floorName;
  297.   int   floorNo, newRoom = 0, rover;
  298.   outFlag = IMPERVIOUS;
  299.   if (mode == 'S')
  300.     {
  301.     mPrintf("[%s] goto ", FloorTab[roomTab[thisRoom].rtFlIndex].FlName);
  302.     };
  303.   if (getNormStr("", floorName, NAMESIZE, BS_VALID) == BACKED_OUT)
  304.     {
  305.     if (mode == 'S')
  306.       for (rover = 0; rover < strLen(FloorTab[roomTab[thisRoom].rtFlIndex].FlName)+7; rover++) mPrintf("\b \b");
  307.     return BACKED_OUT;
  308.     };
  309.   if (strLen(floorName) != 0)
  310.     {
  311.     if ((floorNo = FindFloor(floorName, TRUE)) == ERROR)
  312.       {
  313.       Output_Citadel_Message("NODRFD", (long)floorName,NULL, NULL);
  314.       return GOOD_SELECT;
  315.       };
  316.     if ((newRoom = FloorRunner(FirstRoom(floorNo), FindAny)) == ERROR)
  317.       {
  318.       Output_Citadel_Message("NOKNRM",(long) FloorTab[floorNo].FlName, NULL, NULL );
  319.       return GOOD_SELECT;
  320.       };
  321.     }
  322.   else
  323.     {
  324.     floorNo = thisFloor;
  325.     for (rover = 0; rover < TopFloor; rover++)
  326.     if (rover != floorNo && FloorTab[rover].FlInuse)
  327.       {
  328.       newRoom = FirstRoom(rover);
  329.       if ((newRoom = FloorRunner(newRoom, NSRoomHasNew)) != ERROR)
  330.       break;
  331.  
  332.       }
  333.     if (rover == TopFloor)    newRoom = 0;
  334.  
  335.     }
  336.   if (mode == 'S') FloorRunner(thisRoom, FSroom);
  337.   gotoRoom(roomTab[newRoom].rtname, mode);
  338.   return GOOD_SELECT;
  339.  
  340.   }
  341. /*
  342. * FindFloor()
  343. *
  344. * This function returns index for the given floor name.
  345. */
  346. int FindFloor(label name, char doPartial)
  347.   {
  348.   int rover;
  349.   for (rover = 0; rover < TopFloor; rover++)
  350.     {
  351.     if (strCmpU(name, FloorTab[rover].FlName) == SAMESTRING &&
  352.     FloorTab[rover].FlInuse)
  353.       {
  354.       return rover;
  355.  
  356.       }
  357.  
  358.     }
  359.   if (doPartial)
  360.   for (rover = 0; rover < TopFloor; rover++)
  361.     {
  362.     if (FloorTab[rover].FlInuse &&
  363.     matchString(FloorTab[rover].FlName, name,
  364.     lbyte(FloorTab[rover].FlName)) != NULL)
  365.     return rover;
  366.  
  367.     }
  368.   return ERROR;
  369.  
  370.   }
  371. /*
  372. * FAide()
  373. *
  374. * This function handles the floor-oriented aide commands.
  375. */
  376. char FAide()
  377.   {
  378.   char *FloorAideOpts[] =
  379.     {
  380.     "Create Floor\n", "Delete empty floors\n", "Move rooms\n",
  381.     "Kill Floor\n", "Rename Floor\n", "Floor moderator\n",
  382.     "Invite users to floor", "Withdraw users from floor", "\b", ""
  383.  
  384.     };
  385.   if (!aide)
  386.     {
  387.     if (loggedIn && strCmpU(logBuf.lbname, FloorTab[thisFloor].FlModerator) ==
  388.     SAMESTRING)
  389.       {
  390.       RenameFloor();
  391.       return GOOD_SELECT;
  392.  
  393.       }
  394.     else
  395.     return BAD_SELECT;    /* Indicates problem */
  396.  
  397.     }
  398.   RegisterThisMenu("aideflr.mnu", FloorAideOpts);
  399.   switch (GetMenuChar())
  400.     {
  401.     case 'C': CreateFloor();      break;
  402.     case 'D': DeleteFloors();     break;
  403.     case 'M': MoveRooms();        break;
  404.     case 'K': KillFloor();        break;
  405.     case 'R': RenameFloor();      break;
  406.     case 'F': FlModerator();      break;
  407.     case 'I': FInvite();        break;
  408.     case 'W': FWithdraw();        break;
  409.     case '\b': return BACKED_OUT;
  410.  
  411.     }
  412.   return GOOD_SELECT;
  413.  
  414.   }
  415. /*
  416. * FlModerator()
  417. *
  418. * This function handles the floor moderator.
  419. */
  420. void FlModerator()
  421.   {
  422.   label buffer;
  423.   if (WhoIsModerator(buffer))
  424.     {
  425.     strCpy(FloorTab[thisFloor].FlModerator, buffer);
  426.     putFloor(thisFloor);
  427.     ZeroMsgBuffer(&msgBuf);
  428.     sPrintf(msgBuf.mbtext, "%s's moderator set to %s by %s.",
  429.     FloorTab[thisFloor].FlName, buffer, logBuf.lbname);
  430.     aideMessage(NULL,FALSE);
  431.  
  432.     }
  433.  
  434.   }
  435. /*
  436. * DeleteFloors()
  437. *
  438. * This function deletes empty floors.
  439. */
  440. void DeleteFloors()
  441.   {
  442.   int rover, count = 0;
  443.   ZeroMsgBuffer(&msgBuf);
  444.   sPrintf(msgBuf.mbtext, "Following empty floors deleted by %s: ",
  445.   logBuf.lbname);
  446.   for (rover = 1; rover < TopFloor; rover++)
  447.     {
  448.     if (FloorTab[rover].FlInuse)
  449.       {
  450.       if (FirstRoom(rover) == ERROR)
  451.         {
  452.         count++;
  453.         FloorTab[rover].FlInuse = FALSE;
  454.         putFloor(rover);
  455.         sPrintf(lbyte(msgBuf.mbtext), "[%s], ", FloorTab[rover].FlName);
  456.  
  457.         }
  458.  
  459.       }
  460.  
  461.     }
  462.   if (count)
  463.     {
  464.     *(lbyte(msgBuf.mbtext) - 2) = '.';
  465.     *(lbyte(msgBuf.mbtext) - 1) = 0;
  466.  
  467.     }
  468.   aideMessage(NULL,FALSE);
  469.  
  470.   }
  471. /*
  472. * MoveRooms()
  473. *
  474. * This function moves a series of rooms into the current floor.
  475. */
  476. void MoveRooms()
  477.   {
  478.   int   CurrentRoom;
  479.   char  *end;
  480.   CurrentRoom = thisRoom;
  481.   GlobalFloor = thisFloor;
  482.   MoveCount = 0;
  483.   ZeroMsgBuffer(&msgBuf);
  484.   sPrintf(msgBuf.mbtext, "Following rooms moved to floor %s by %s: ",
  485.   FloorTab[thisFloor].FlName, logBuf.lbname);
  486.   getList(MoveToFloor, "Rooms to move to this floor", NAMESIZE, FALSE);
  487.   getRoom(CurrentRoom);       /* MoveToFloor changes thisRoom & roomBuf */
  488.   if (MoveCount != 0)
  489.     {
  490.     end = lbyte(msgBuf.mbtext);
  491.     *(end - 2) = '.';
  492.     *(end - 1) = 0;
  493.     aideMessage(NULL,FALSE);
  494.  
  495.     }
  496.  
  497.   }
  498. /*
  499. * MoveToFloor()
  500. *
  501. * This function will move a single room to a floor.
  502. */
  503. int MoveToFloor(char *name)
  504.   {
  505.   int roomNo;
  506.   if ((roomNo = roomExists(name)) == ERROR)
  507.     {
  508.     Output_Citadel_Message("NOROOM",(long)name,NULL,NULL);
  509.     return TRUE;
  510.  
  511.     }
  512.   if (   roomNo == LOBBY  ||  roomNo == MAILROOM  ||  roomNo == AIDEROOM  )
  513.     {
  514.     if (!getYesNo("WRMVSP")) return TRUE;
  515.  
  516.     }
  517.   MoveCount++;
  518.   getRoom(roomNo);
  519.   roomBuf.rbFlIndex = GlobalFloor;
  520.   putRoom(roomNo);
  521.   noteRoom();
  522.   sPrintf(lbyte(msgBuf.mbtext), "%s, ", formRoom(thisRoom, FALSE, FALSE));
  523.   return TRUE;
  524.  
  525.   }
  526. /*
  527. * RenameFloor()
  528. *
  529. * This function renames a floor.
  530. */
  531. void RenameFloor()
  532.   {
  533.   label FloorName;
  534.   int   ReturnNo;
  535.   if (thisFloor == 0)
  536.     {
  537.     Output_Citadel_Message("USECFG",NULL ,NULL,NULL);
  538.     return ;
  539.  
  540.     }
  541.   if (!getXString("FLRNIT", FloorName, NAMESIZE, NULL, NULL))
  542.   return ;
  543.   if ((ReturnNo = FindFloor(FloorName, FALSE)) != ERROR)
  544.     {
  545.     if (ReturnNo != thisFloor)
  546.       {
  547.       Output_Citadel_Message("ALRYFR",(long)FloorName,NULL,NULL);
  548.       return;
  549.  
  550.       }
  551.  
  552.     }
  553.   ZeroMsgBuffer(&msgBuf);
  554.   sPrintf(msgBuf.mbtext, "The floor %s renamed to %s by %s.",
  555.   FloorTab[thisFloor].FlName, FloorName, logBuf.lbname);
  556.   strCpy(FloorTab[thisFloor].FlName, FloorName);
  557.   putFloor(thisFloor);
  558.   aideMessage(NULL,FALSE);
  559.  
  560.   }
  561. /*
  562. * CreateFloor()
  563. *
  564. * This function creates a floor.
  565. */
  566. void CreateFloor()
  567.   {
  568.   label FloorName;
  569.   int   rover;
  570.   if (  thisRoom == LOBBY ||
  571.   thisRoom == MAILROOM ||
  572.   thisRoom == AIDEROOM  )
  573.     {
  574.     Output_Citadel_Message("CCRFLR",NULL, NULL, NULL);
  575.     return ;
  576.  
  577.     }
  578.   if (!getXString("FLRNIT", FloorName, NAMESIZE, NULL, NULL))
  579.   return ;
  580.   if (FindFloor(FloorName, FALSE) != ERROR)
  581.     {
  582.     Output_Citadel_Message("ALRYFR",(long)FloorName,NULL,NULL);
  583.     return;
  584.  
  585.     }
  586.   for (rover = 1; rover < TopFloor; rover++)
  587.   if (!FloorTab[rover].FlInuse) break;
  588.   if (rover == TopFloor)
  589.     {
  590.     FloorTab = (struct floor *) realloc(FloorTab,
  591.     sizeof *FloorTab * ++TopFloor);
  592.  
  593.     }
  594.   roomBuf.rbFlIndex = rover;
  595.   FloorTab[rover].FlInuse = TRUE;
  596.   strCpy(FloorTab[rover].FlName, FloorName);
  597.   memset(FloorTab[rover].FlModerator, '\0',sizeof(label));
  598.   putFloor(rover);
  599.   putRoom(thisRoom);
  600.   noteRoom();
  601.   ZeroMsgBuffer(&msgBuf);
  602.   sPrintf(msgBuf.mbtext, "The floor %s created by %s.", FloorName,
  603.   logBuf.lbname);
  604.   aideMessage(NULL,FALSE);
  605.  
  606.   }
  607. /*
  608. * putFloor()
  609. *
  610. * This will put a floor record out to disk.
  611. */
  612. void putFloor(int i)
  613.   {
  614.   SYS_FILE name;
  615.   FILE *fd;
  616.   long r;
  617.   extern char *R_W_ANY;
  618.   makeSysName(name, "ctdlflr.sys", &cfg.floorArea);
  619.   if ((fd = safeopen(name, R_W_ANY)) == NULL)
  620.   crashout("Couldn't open the floor file for update!");
  621.   r = i * sizeof *FloorTab;
  622.   fseek(fd, r, 0);
  623.   if (fwrite(FloorTab + i, sizeof *FloorTab, 1, fd) != 1)
  624.   crashout("?putFloor(): write failed!");
  625.   fclose(fd);
  626.  
  627.   }
  628. /*
  629. * KillFloor()
  630. *
  631. * This function kills a floor.
  632. */
  633. void KillFloor()
  634.   {
  635.   int CurrentFloor, CurrentRoom;
  636.   if (roomBuf.rbFlIndex == 0)
  637.     {
  638.     Output_Citadel_Message("NOKILF",NULL ,NULL,NULL);
  639.     return;
  640.  
  641.     }
  642.   if (!getYesNo("CONFRM")) return;
  643.   ZeroMsgBuffer(&msgBuf);
  644.   sPrintf(msgBuf.mbtext, "Floor %s killed by %s.",
  645.   FloorTab[thisFloor].FlName, logBuf.lbname);
  646.   aideMessage(NULL,FALSE);
  647.   CurrentFloor = thisFloor;   /* #define in CTDL.H */
  648.   CurrentRoom  = thisRoom;
  649.   maim = getYesNo("MVALLM");
  650.   FloorRunner(thisRoom, MaimOrKill);
  651.   FloorTab[CurrentFloor].FlInuse = FALSE;
  652.   putFloor(CurrentFloor);
  653.   /* due to behavior of MaimOrKill */
  654.   getRoom((!maim) ? LOBBY : CurrentRoom);
  655.  
  656.   }
  657. /*
  658. * MaimOrKill()
  659. *
  660. * This will kill or move a room to the main floor.
  661. */
  662. int MaimOrKill(int i)
  663.   {
  664.   getRoom(i);
  665.   if (maim)
  666.     {
  667.     roomBuf.rbFlIndex = 0;
  668.  
  669.     }
  670.   else
  671.     {
  672.     roomBuf.rbflags.INUSE = FALSE;
  673.  
  674.     }
  675.   putRoom(i);
  676.   noteRoom();
  677.   return FALSE;
  678.  
  679.   }
  680. /*
  681. * FKnown()
  682. *
  683. * This function will handle the ticklish task of floor display.
  684. */
  685. char FKnown(char mode)
  686.   {
  687.   int         rover, roomNo;
  688.   extern int  DirAlign;
  689.   extern char AlignChar;
  690.   switch (mode)
  691.     {
  692.     case FORGOTTEN:
  693.       Output_Citadel_Message("FORGFL",NULL,NULL,NULL);
  694.     ShowNew = 2;
  695.     SelNew = TRUE;
  696.     RunDisplay();
  697.     SelNew = FALSE;
  698.     break;
  699.     case INT_NOVICE:
  700.     case INT_EXPERT:
  701.     case NOT_INTRO:
  702.     if (SelNew)
  703.       Output_Citadel_Message("RMUNRF",(long)FloorTab[thisFloor].FlName,NULL,NULL);
  704.     ShowNew = TRUE;
  705.     FloorRunner(thisRoom, DispRoom);
  706.     if (mode == INT_NOVICE || mode == NOT_INTRO)
  707.       {
  708.       Output_Citadel_Message("NOUNSN",NULL,NULL,NULL);
  709.       ShowNew = FALSE;
  710.       FloorRunner(thisRoom, DispRoom);
  711.  
  712.       }
  713.     if (SelNew)
  714.       {
  715.       Output_Citadel_Message("OTFLUM",NULL,NULL,NULL);
  716.       for (rover = 0; rover < TopFloor; rover++)
  717.         {
  718.         if (rover != roomBuf.rbFlIndex)
  719.           {
  720.           roomNo = FirstRoom(rover);
  721.           if (FloorRunner(roomNo, RoomHasNew) != ERROR)
  722.             Output_Citadel_Message("FLRNNL", (long)FloorTab[rover].FlName,NULL,NULL);
  723.  
  724.           }
  725.  
  726.         }
  727.  
  728.       }
  729.     break;
  730.     case DR_SEL:
  731.     case SH_SEL:
  732.     case PR_SEL:
  733.     case ANON_SEL:
  734.     case READONLY:
  735.     RunDisplay();
  736.     break;
  737.     default:
  738.     SelNew = TRUE;
  739.     doCR();
  740.     Output_Citadel_Message("FLRWUR", NULL,NULL,NULL);
  741.     ShowNew = FoundNew = TRUE;
  742.     RunDisplay();
  743.     doCR();
  744.     Output_Citadel_Message("FLRWNR", NULL,NULL,NULL);
  745.     ShowNew = FoundNew = FALSE;
  746.     RunDisplay();
  747.     SelNew = FALSE;
  748.  
  749.     }
  750.   return GOOD_SELECT;
  751.  
  752.   }
  753. /*
  754. * RunDisplay()
  755. *
  756. * This will do the actual work of displaying in Floor mode.
  757. */
  758. void RunDisplay()
  759.   {
  760.   extern int  DirAlign;
  761.   extern char AlignChar;
  762.   int rover, roomNo;
  763.   AlignChar = ' ';
  764.   for (rover = 0; rover < TopFloor; rover++)
  765.     {
  766.     if (FloorTab[rover].FlInuse)
  767.       {
  768.       roomNo = FirstRoom(rover);
  769.       if (FloorRunner(roomNo, CheckFloor) != ERROR)
  770.         {
  771.         DispFloorName(rover);
  772.         FloorRunner(roomNo, DispRoom);
  773.         DirAlign = 0;
  774.  
  775.         }
  776.  
  777.       }
  778.  
  779.     }
  780.  
  781.   }
  782. /*
  783. * DispFloorName()
  784. *
  785. * This function displays a floor name with periods, etc...
  786. */
  787. void DispFloorName(int FloorNo)
  788.   {
  789.   int i;
  790.   extern int DirAlign;
  791.   extern char AlignChar;
  792.   Output_Citadel_Message("FLRSNL", (long)FloorTab[FloorNo].FlName,NULL,NULL);
  793.   if (termWidth >= 50)
  794.     {
  795.     DirAlign = 24;
  796.     AlignChar = ' ';
  797.     for (i = strLen(FloorTab[FloorNo].FlName); i < 21; i++)
  798.     mPrintf(".");
  799.  
  800.     }
  801.   else mPrintf("-");
  802.  
  803.   }
  804. /*
  805. * These functions are used as arguments to FloorRunner
  806. */
  807. /*
  808. * RoomHasNew()
  809. *
  810. * This returns TRUE if room has new messages for the current user.
  811. */
  812. int RoomHasNew(int i)
  813.   {
  814.   return (    roomTab[i].rtlastMessage >
  815.   logBuf.lbvisit[logBuf.lbgen[i] & CALLMASK] &&
  816.   roomTab[i].rtlastMessage >= cfg.oldest     );
  817.  
  818.   }
  819. /*
  820. * CheckFloor()
  821. *
  822. * This multipurpose function returns true of one of the combinations is
  823. * true.
  824. */
  825. int CheckFloor(int i)
  826.   {
  827.   #ifdef OLD_STYLE
  828.   if (( SelDirs   &&   roomTab[i].rtflags.ISDIR   ) ||
  829.   ( SelShared &&   roomTab[i].rtflags.SHARED  ) ||
  830.   ( SelPriv   &&   !roomTab[i].rtflags.PUBLIC ) ||
  831.   ( SelAnon   &&   roomTab[i].rtflags.ANON )    ||
  832.   ( SelRO     &&   roomTab[i].rtflags.READ_ONLY )    ||
  833.   ( SelNew && (ShowNew == 2 || (RoomHasNew(i) && FoundNew) ||
  834.   (!RoomHasNew(i) && !FoundNew))))
  835.   return TRUE;
  836.   #else
  837.   if (FlagCheck(i) ||
  838.   ( SelNew && (ShowNew == 2 || (RoomHasNew(i) && FoundNew) ||
  839.   (!RoomHasNew(i) && !FoundNew))))
  840.   return TRUE;
  841.   #endif
  842.   return FALSE;
  843.  
  844.   }
  845. /*
  846. * NSRoomHasNew()
  847. *
  848. * TRUE if room has new messages and isn't skipped.
  849. */
  850. int NSRoomHasNew(int i)
  851.   {
  852.   if (!roomTab[i].rtflags.SKIP && RoomHasNew(i))
  853.   return TRUE;
  854.   if (roomTab[i].rtflags.SKIP) /* Kludge this in -- ugly but useful */
  855.   HasSkipped = TRUE;
  856.   return FALSE;
  857.  
  858.   }
  859. /*
  860. * DispRoom()
  861. *
  862. * This function will display a room name.
  863. */
  864. int DispRoom(int i)
  865.   {
  866.   char HasNew;
  867.   extern char shownHidden;
  868.   HasNew = RoomHasNew(i);
  869.   if (FlagCheck(i) ||
  870.   ( SelNew &&
  871.   (ShowNew == 2 || (HasNew && ShowNew == 1) ||
  872.   (!HasNew && !ShowNew))))
  873.     {
  874.     Output_Citadel_Message("DISPRM",(long)formRoom(i, TRUE, TRUE),NULL,NULL);
  875.     if (!roomTab[i].rtflags.PUBLIC) shownHidden = TRUE;
  876.     if (SelDirs && HalfSysop())
  877.       {
  878.       if (FindDirName(i) != NULL)
  879.         Output_Citadel_Message("DISPDR",(long)FindDirName(i),NULL,NULL);
  880.       else
  881.         Output_Citadel_Message("DISPNF",NULL,NULL,NULL);
  882.  
  883.       }
  884.  
  885.     }
  886.   return FALSE;
  887.  
  888.   }
  889. /*
  890. * Zroom()
  891. *
  892. * This lets us Zforget a room.  Used for ;Z.
  893. */
  894. int Zroom(int i)
  895.   {
  896.   int r;
  897.   if (     i == LOBBY    ||
  898.   i == MAILROOM ||
  899.   i == AIDEROOM      )
  900.     {
  901.     return FALSE;
  902.  
  903.     }
  904.   r = (roomTab[i].rtgen + FORGET_OFFSET) % MAXGEN;
  905.   logBuf.lbgen[i] = r << GENSHIFT;
  906.   return FALSE;
  907.  
  908.   }
  909. /*
  910. * FSroom()
  911. *
  912. * This will skip a room on a floor.
  913. */
  914. int FSroom(int i)
  915.   {
  916.   roomTab[i].rtflags.SKIP = 1;     /* Set bit */
  917.   return FALSE;
  918.  
  919.   }
  920. /*
  921. * FindAny()
  922. *
  923. * This finds any known room on a floor.
  924. */
  925. int FindAny(int i)
  926.   {
  927.   return TRUE;        /* My, that was easy... */
  928.  
  929.   }
  930. static int FlagCheck(int i)
  931.   {
  932.   if (( SelDirs   &&   roomTab[i].rtflags.ISDIR   ) ||
  933.   ( SelShared &&   roomTab[i].rtflags.SHARED  ) ||
  934.   ( SelPriv   &&   !roomTab[i].rtflags.PUBLIC ) ||
  935.   ( SelAnon   &&   roomTab[i].rtflags.ANON )    ||
  936.   ( SelRO     &&   roomTab[i].rtflags.READ_ONLY ))
  937.   return TRUE;
  938.   return FALSE;
  939.  
  940.   }
  941.